/* $Id tongying.cai@gmail.com 2011-7-2 05:15 exp$ */
#include <bolt.h>
#include <prot.h>
#include "basic.h"

BOLT(gtp_set_err_teid, "gtp set err-teid <teid>")
{
  uint32_t eteid;
  if(!str2u32(pop_argz(), &eteid)) {
    printf("Invalid err teid.\n");
    return;
  }
  gtp_set_err_teid(eteid);
}

static void gtp_err_teid_profile(void *desc)
{
  uint32_t err_teid = gtp_get_err_teid();
  if (err_teid != 0)
    cmd_load_profile(desc, "gtp set err-teid 0x%x\n", err_teid);
}


BOLT(gtp_set_ext_list, "gtp set ext-list <index> <ext-type>")
{
  uint32_t index;
  uint8_t val;

  if(!str2u8(pop_argz(), &val)) {
    printf("Invalid extention type.\n");
    return;
  }
  if(!str2u32(pop_argz(), &index) || index >= EXT_LIST_MAX) {
    printf("Invalid extention index.\n");
    return;
  }
  gtp_set_ext_list(index, val);
}

static void gtp_ext_list_profile(void *desc)
{
   uint8_t ext;
   uint32_t i;

   for (i = 0; gtp_get_ext_list(i, &ext) == 0; ++i) {
      if (ext != 0)
         cmd_load_profile(desc, "gtp set ext-list %u 0x%x\n", i, ext);
   }
}

BOLT(set_gtp_msg, "gtp set msg-type <type>")
{
   uint8_t msg;
   const char *ptr = pop_argz();

   if (ptr == NULL) {
      printf("Invalid parameter\n");
      return;
   }
   msg = gtp_msg2u8(ptr);

   if (msg == 0) {
      printf("invalid parameter %s, should be:\n", ptr);
      gtp_msg_show();
   } else {
      gtp_set_msg(msg);
   }
}

static void gtp_msg_profile(void *desc)
{
   char name[32];
   uint8_t msg = gtp_get_msg();
   if (msg != MSG_GTPU)
      cmd_load_profile(desc, "gtp set message %s\n", gtp_msg2str(msg, name, sizeof(name)));
}


BOLT(show_gtp_entry, "gtp show entry")
{
   gtp_show_entry();
}

BOLT(show_gtp_statis, "gtp show statis")
{
   gtp_show_statis();
}

BOLT(show_gtp_detail, "gtp show detail <msg-type>")
{
  uint8_t msg_type;
  if(!str2u8(pop_argz(), &msg_type)) {
     printf("Invalid gtp message type.\n");
     return;
  }
  gtp_show_detail(msg_type);
}

BOLT(gtp_show_ext_hdr_type, "gtp show ext-hdr-type")
{
   gtp_show_ext_hdr_type();
}

BOLT(gtp_set_ext_hdr_type, "gtp set ext-hdr type <ext-type>")
{
   uint8_t ext_type;
   if(!str2u8(pop_argz(), &ext_type)) {
      printf("Invalid extension header type.\n");
      return;
   }
   gtp_set_ext_hdr_type(ext_type);
}

BOLT(gtp_set_ext_hdr_nested_level, "get set ext-hdr nested-level <level>")
{
    uint8_t ext_nested_level;
    if (!str2u8(pop_argz(), &ext_nested_level)) {
        printf("Invalid extension header nested level. range(1~16)\n");
        return;
    }

    if (ext_nested_level < 1 || ext_nested_level > 16)
    {
        printf("Invalid extension header nested level. range(1~16)\n");
        return;
    }
    gtp_set_ext_hdr_nested_level(ext_nested_level);
}

static void gtp_ext_hdr_profile(void *desc)
{
   uint8_t ext_hdr_type = gtp_get_ext_hdr_type();
   uint8_t ext_hdr_nested_level = gtp_get_ext_hdr_nested_level();

   if (ext_hdr_type != 0)
      cmd_load_profile(desc, "gtp set ext-header 0x%02x\n", ext_hdr_type);

   if (ext_hdr_nested_level != 0)
      cmd_load_profile(desc, "gtp set ext-header nested 0x%02x\n", ext_hdr_nested_level);
}


BOLT(gtp_set_echo_disabled, "gtp set echo diabled")
{
   gtp_set_echo_reply(false);
}


BOLT(gtp_set_echo_enabled, "gtp set echo enabled")
{
   gtp_set_echo_reply(true);
}

BOLT(gtp_set_sflag_enabled, "gtp set sflag enabled")
{
    gtp_set_sflag(true);
}

BOLT(gtp_set_sflag_disabled, "gtp set sflag disabled")
{
    gtp_set_sflag(false);
}

BOLT(gtp_set_pnflag_enabled, "gtp set pnflag enabled")
{
    gtp_set_pnflag(true);
}

BOLT(gtp_set_pnflag_disabled, "gtp set pnflag disabled")
{
    gtp_set_pnflag(false);
}

static void gtp_echo_profile(void *desc)
{
   if (gtp_get_echo_reply())
      cmd_load_profile(desc, "gtp set echo enabled\n");
}

static void gtp_sflag_profile(void *desc)
{
   if (gtp_get_sflag())
      cmd_load_profile(desc, "gtp set sflag enabled\n");
}

static void gtp_pnflag_profile(void *desc)
{
  if (gtp_get_pnflag())
    cmd_load_profile(desc, "gtp set pnflag enabled\n");
}

#define GTP_TEST_LEN 20
static uint8_t gtp_test_buf[GTP_TEST_LEN];

BOLT(send_gtp, "gtp <id> send <dts-ip> <dst-port>")
{
   uint32_t gtp_id;
   sockaddr_t dst;
   uint16_t port;
   int len;
   memset(&dst, 0, sizeof(dst));
   if(!str2u16(pop_argz(), &port)) {
      printf("Invalid destination port.\n");
      return;
   }
   if (!ip2addr(pop_argz(), &dst.v0)) {
      printf ("Invalid destination IP.\n");
      return;
   }
   addr_set_port(&dst, port);
   if(!str2u32(pop_argz(), &gtp_id)) {
      printf("Invalid gtp id.\n");
      return;
   }
   len = gtp_send((int)gtp_id, &dst, gtp_test_buf, GTP_TEST_LEN);
   printf("Send GTP, len=%d\n", len);
}

BOLT(create_gtp, "gtp <id> create <src-teid> <dst-teid> <udp-id>")
{
   uint32_t src_teid, dst_teid, udp_id, gtp_id;
   int id;
   const char *argz=pop_argz();

   if (!str2u32(argz, &udp_id)) {
      printf("Invalid udp id.\n");
      return;
   }

   argz=pop_argz();
   if (!str2u32(argz, &dst_teid)) {
      printf("Invalid destination tunnel id.\n");
      return;
   }
   argz=pop_argz();
   if (!str2u32(argz, &src_teid)) {
      printf("Invalid source tunnel id.\n");
      return;
   }
   if (!str2u32(argz, &gtp_id)) {
      printf("Invalid gtp id.\n");
      return;
   }
   id = gtp_create((int)gtp_id, src_teid, dst_teid, (int)udp_id);
   printf("The gtp id is %d\n", id);
}

BOLT(release_gtp, "gtp <id> release")
{
  uint32_t gtp_id;
  if(!str2u32(pop_argz(), &gtp_id)) {
    printf("Invalid gtp id.\n");
    return;
  }
  gtp_release((int)gtp_id);
}

BOLT_PROFILE(gtp, "udp", cmd_gtp_profile, desc)
{
  gtp_msg_profile(desc);
  gtp_ext_hdr_profile(desc);
  gtp_err_teid_profile(desc);
  gtp_echo_profile(desc);
  gtp_ext_list_profile(desc);
  gtp_sflag_profile(desc);
  gtp_pnflag_profile(desc);
}

